﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Cryptography;

namespace Common.Cryptography
{
    public static class RC2Helper
    {

        #region Global Var(s)

        private static RC2 RC2Eninge = null;
        private const int RC2KeySize = 16;
        private const int RC2IVSize = 8;

        #endregion

        #region Basic

        public static void init(string strPassword)
        {
            if (String.IsNullOrEmpty(strPassword))
                throw new ArgumentNullException("strPassword");

            RC2Eninge = RC2.Create();
            RC2Eninge.Key = CryptographyHelper.GetKeyFromPassword(strPassword, RC2KeySize);
            RC2Eninge.IV = CryptographyHelper.GetKeyFromPassword(strPassword, RC2IVSize);
        }

        public static void free()
        {
            if (RC2Eninge.isNull() == false)
                RC2Eninge.Clear();
        }

        #endregion

        #region Encryption

        public static byte[] Encrypt(byte[] RawData)
        {
            if (RC2Eninge.isNull())
                throw new ArgumentNullException("Must call init frist!");
            if (RawData.isNull() || RawData.Length < 1)
                throw new ArgumentNullException("RawData");

            MemoryStream ms = null;
            CryptoStream cs = null;
            BinaryWriter bw = null;

            try
            {
                ICryptoTransform ct = RC2Eninge.CreateEncryptor(RC2Eninge.Key, RC2Eninge.IV);
                ms = new MemoryStream();
                cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
                bw = new BinaryWriter(cs);

                bw.Write(RawData);
            }
            finally
            {
                if (bw.isNull() == false)
                    bw.Close();
                if (cs.isNull() == false)
                    cs.Close();
                if (ms.isNull() == false)
                    ms.Close();
            }

            return ms.ToArray();
        }


        #endregion

        #region Decryption

        public static byte[] Decrypt(byte[] RawData)
        {
            if (RC2Eninge.isNull())
                throw new ArgumentNullException("Must call init frist!");
            if (RawData.isNull() || RawData.Length < 1)
                throw new ArgumentNullException("RawData");

            MemoryStream ms = null;
            CryptoStream cs = null;
            BinaryReader br = null;
            byte[] dptData = null;

            try
            {
                ICryptoTransform ct = RC2Eninge.CreateDecryptor(RC2Eninge.Key, RC2Eninge.IV);
                ms = new MemoryStream(RawData);
                cs = new CryptoStream(ms, ct, CryptoStreamMode.Read);
                br = new BinaryReader(cs);

                dptData = br.ReadBytes(RawData.Length);
            }
            finally
            {
                if (br.isNull() == false)
                    br.Close();
                if (cs.isNull() == false)
                    cs.Close();
                if (ms.isNull() == false)
                    ms.Close();
            }

            return dptData;
        }


        #endregion
    }
}
